/*
	A gcd application written for NIOS II using a CFDF structured approach
*/

/*
#	Register usage
# Since it is a small application, most values of global items are held in registers
# they are chosen arbitrarily
	r17	operand 1
	r10 operand 1 biner
	r18	operand 2
	r11 operand 2 biner
	r19 result 
	r9  result biner
	
	r20	BTN_BASEADDR
	r21	SW-BASEADDR
	r22 SEG7L_BASEADDR L-part (displays lower 4 digits)
	r23 SEG7H_BASEADDR H-Part
	r24	CONV_SEG7_BASE
*/	
	.equ SEG7L_BASEADDR, 0x10000020				/* SEG7[3..0] base address */	
	.equ SEG7H_BASEADDR, 0x10000030				/* SEG7[3..0] base address */	
	.equ	BTN_BASEADDR, 0x10000050				/* Startaddress Push Buttons */
	.equ SW_BASEADDR, 0x10000040
	.equ ADD, 0x0
	.equ SUB, 0x1
	.equ MULT, 0x2
	.equ DIV, 0x3
	.equ POW, 0x4
	.data /* data follows */
	
CONV_SEG7_BASE:
	.byte	0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x58,0x5e,0x79,0x71
STACKE:			# stack end is here, starts at STACKA and grows to lower addresses, as usual
	.space 0x100
STACKA:		
	.global _start
	.text
/*
* main program
* initiates computation
* controls it
*/

_start:
	movia	sp, STACKA-4				# Initiate stack 
	movia r20, BTN_BASEADDR		# load start addresses
	movia	r21, SW_BASEADDR		
	movia r22, SEG7L_BASEADDR
	movia r23, SEG7H_BASEADDR
	movia r24, CONV_SEG7_BASE
	addi	r17, zero, 1					# initiate global variables with 1
	addi  r18, zero, 1
	addi	r19,zero, 1
	addi  r11,zero, 15
	stwio r11, 12(r20)				# clear btn edges with start 
mainloopS:	
  addi  r2, zero, 1         # waitBtn(mask to test btn 1
	call waitBtn
Op1:
  call readnumber_display   # call of readnumber with integrated display	
	add  r17, r2, zero					# store result 
Operation:
	call Enter_Operation
	add r1, r2, zero
Op2:
  call readnumber_display   # call of readnumber with integrated display	
	add  r18,  r2, zero				# store result 

MATH:
	call compute
	call displaynumber	
	call _start

	
/*
COMP:
	call gcd
	add  r19, r2, zero
  addi  r3, zero, 4           # waitbutton(PB2-Mask)	
	call waitBtn
	add		r3, r19, zero
	call  displaynumber
	br 	mainloopS	*/	/* it should work forever!*/

/*
  waitBtn
	wait for a button press
	input r2: button mask
	returns Button flag set
	uses r11, r12
*/	
waitBtn:
 	ldwio	r11, 12(r20)				# load edge capture of button IO
	beq   r11, zero, waitBtn  # no press
	stwio r11, 12(r20)        # clear flag
  and   r12, r11, r2  		  # only buttons specified in r2 are tested
	beq		r12, zero, waitBtn  # if not new event, wait	
	add		r2, r12, zero				# return flag 			
  ret

/*
*	displaynumber
* displays a number on the 7Segment display
* Parameters
* r3: number to be displayed
* Uses registers r11..r19 freely
*
* It is assumed that the registers r20.. are properly defined
* register usage
*	r11: number copy, is reduced digit by digit starting with digit 0
*	r12: counter for 4 digits 
*	r15: flag showing whether L-part or H-Part is displayed
*	r16: converted pattern for output on 7segments
*/

displaynumber:
  add		r11, r3, zero				# r11 contains number part 
	add   r15, zero, zero			# r15 for number part (0: L, 1: H)
dnloop0S:										# do {
	add   r16, zero, zero     #   clear r16 (used for displaypattern
	addi	r12, zero, 4				#   for (r12= 4; r12 != 0; r12--)
dnloop01S:
	beq		r12, zero, dnloop01E#     loop control
	srli	r16, r16, 8					#     place for new digit pattern 
 	andi  r13, r11, 0xf				#     isolate digit
	add 	r14, r24, r13				#     compute address of number representation
	ldbu	r13, 0(r14)					#     and load pattern for digit
	slli	r13, r13, 24				#     shift pattern to leftmost byte in register
	or		r16, r16, r13				#     or it with the patterns of the other digits
  srli	r11, r11, 4         #     next digit 
	subi	r12, r12, 1					#     for index decr.
	br		dnloop01S						#   }  to start of loop
dnloop01E:	                      
	bne		r15, zero, dnloop0E	#   break after 2nd traversing of dnloop0 
	stwio	r16, 0(r22)					#   output lower part
	addi	r15, r15, 1
	br		dnloop0S            # } while true (loop break see above)
dnloop0E:                         
  stwio	r16, 0(r23)					# output higher part
	ret

/*
  readdigit
	reads a digit 
	returns it in r2
	if btn2 is pressed, it returns 16

	uses working register r2
	assumes io address registers are set 
*/
readdigit:
	subi	sp, sp, 4						# push ra
	stw		ra, 0(sp)
  addi	r2, zero, 6					# waitBtn(mask PB2|PB1)
	call  waitBtn
  andi	r2, r2, 4						# test Btn 2
	bne	r2, zero, readdigite	# must be Pb2 => end
	ldwio r2, 0(r21)          # read switches
	andi  r2, r2, 0xf         # isolate bit 3..0
	ldw		ra, 0(sp)
	addi 	sp, sp, 4
	ret
readdigite:
	addi  r2, zero, 16        # convention to show Press of btn2
	ldw		ra, 0(sp)						# pop ra
	addi 	sp, sp, 4						
	ret
/*
  readnumber_display
  in parallel reads number and displays it
  r2: return register 
	register usage
  r3: parameter for displaynumber 	
	r4: number collected up to that moment
	r5: number counter (max. 8 digits, rest is ignored)
*/
readnumber_display:
	subi	sp, sp, 4						# push ra (nested calls)
	stw		ra, 0(sp)
  add		r4, zero, zero 			# clear r4
	addi	r5, r0, 8           # load max # digits 
rdloop:
  call readdigit
  andi	r6, r2, 16 					# test PB2-Mask
	bne		r6, zero, rdloope		# PB2 was pressed, since result 16 => break
	slli  r4, r4, 4						# shift already read pattern to left 1 digit (4 bit)
	or		r4, r2, r4 					# and or in the new digit
	add		r3, zero, r4				# displaynumber(r4)
	call	displaynumber				# 
	subi	r5, r5, 1						# one less
	bgt		r5, zero, rdloop		# try read next
# here 8 digits are read in. ignore until PB2 is pressed
rdloop2:
  call readdigit
  andi	r6, r2, 16 					# test PB2-Mask
	beq		r2, zero, rdloop2		# PB2 was not pressed
rdloope:	
  add		r2, zero, r4				# move working register to r2
	ldw		ra, 0(sp)						# pop ra
	addi 	sp, sp, 4						
	ret

Enter_Operation:
	subi	sp, sp, 4						# push ra
	stw		ra, 0(sp)
  	addi	r2, zero, 6					# waitBtn(mask PB2|PB1)
	call  waitBtn
	ldwio r2, 0(r21)  
	andi  r2, r2, 0x7         # isolate bit 2..0
	ldw		ra, 0(sp)
	addi 	sp, sp, 4
	ret

compute:
	subi	sp, sp, 4						# push ra
	stw		ra, 0(sp)
	movia	r8, ADD	
	beq	r1, r8, ADDIEREN		# operation add
	movia r8, SUB
	beq r1, r8, SUBTRACHIEREN   # operation sub
	movia r8, MULT
	beq r1, r8, MULTIPLICATION
	movia r8, DIV
	beq r1, r8, DIVIDE
	ret
	
DIVIDE:
	div r3, r17, r18
	call displaynumber
	movia r8, 0xf
	ret
	
MULTIPLICATION:
	mul r3, r17, r18
	call displaynumber
	movia r8, 0xf
	ret
	
ADDIEREN:
	add r3, r17, r18
	#subi 	sp, sp, 4
	#ldw		ra, 0(sp)  # laden von sp zu ra
	movia r8, 0xf
	ret
	
SUBTRACHIEREN:
	sub r3, r17, r18
	call displaynumber
	movia r8, 0xf
	ret
	
.end